/*
 * Please leave this Copyright notice in your code if you use it
 * Written by Decebal Mihailescu [http://www.codeproject.com/script/articles/list_articles.asp?userid=634640]
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Option = System.Collections.Generic.KeyValuePair<string, string>;
using WebUtils;
namespace FreeTranslator
{
    public partial class CustomDictionaryForm : Form
    {
        FreeTranslatorForm _parent;
        DataSetHelper _dsHelper;
        Option _from;
        Option _to;
        public CustomDictionaryForm()
        {
            InitializeComponent();
        }
        CustomDict _dataset = null;
        public CustomDictionaryForm(string selection)
            : this()
        {
            //_translatedText = selection;
            _txtCorrected.Text = _txtTranslated.Text = selection.Trim();
            //_txtTranslated.Enabled = _txtTranslated.Text.Length == 0;
        }
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            _parent = this.Owner as FreeTranslatorForm;
            _parent._btnTranslate.Enabled = false;
            _parent._cbxTo.Enabled = false;
            _parent._cbxFrom.Enabled = false;
            _parent._ckbCalcAccuracy.Enabled = false;
            _from = (Option)_parent._cbxFrom.SelectedItem;
            _to = (Option)_parent._cbxTo.SelectedItem;
            Text = string.Format("Corrections for {0} <-> {1} dictionary", _from.Value, _to.Value);

            _lblTranslated.Text = string.Format("Result for {0} <-> {1} translation:", _from.Value, _to.Value);// _to.Value + ':';

            _dataset = _parent.CustomDictDataset;
            _translationTabPage.Text = string.Format("{0}->{1}", _from.Value, _to.Value);
            _reverseTranslationTabPage.Text = string.Format("{0}->{1}", _to.Value, _from.Value);
            //_txtCorrected.Focus();

        }

        protected override void OnActivated(EventArgs e)
        {
            base.OnActivated(e);
            _txtCorrected.Focus();
        }
        protected override void OnClosed(EventArgs e)
        {
            try
            {
                if (_dataset.Tables["Joint"] != null)
                    _dataset.Tables.Remove("Joint");
                TranslatorBase.ShrinkDataSet(_dataset);
                _dataset.WriteXml(FreeTranslatorForm._fileDictLoc);
            }
            catch //(Exception ex)
            {
            }
            finally
            {
                TranslatorBase.RestoreDataSet(_parent._dataset);
            }
            base.OnClosed(e);
            _parent._btnTranslate.Enabled = true;
            _parent._cbxTo.Enabled = true;
            _parent._cbxFrom.Enabled = true;
            _parent._ckbCalcAccuracy.Enabled = true;
            Dispose(false);
        }

        private void _btnReverseTranslate_Click(object sender, EventArgs e)
        {
            //WebUtils.TranslatorBase gt = new WebUtils.GoogleTranslator(_to.Key, _from.Key);
            WebUtils.TranslatorBase gt = TranslatorBase.CreateProvider(this, TranslatorProvider.Google, _to.Key, _from.Key);
            string strTranslation = gt.Translate(_txtTranslated.Text).Trim();
            //_txtRevesed.Text = _txtOriginal.Text = strTranslation;
        }

        private void _btnAddTranslation_Click(object sender, EventArgs e)
        {
            try
            {

                CustomDict.RepositoryRow reprow = null;
                if (_txtCorrected.Text.Length == 0 || _txtTranslated.Text.Length == 0)
                    return;
                DataTable dtInnerJoin;
                if (_dataset.Tables["Joint"] != null)
                    dtInnerJoin = _dataset.Tables["Joint"];
                else
                {
                    if (_dsHelper == null)
                    {
                        DataSet ds = _dataset.Tables[0].DataSet;
                        _dsHelper = new DataSetHelper(ds);
                    }
                    bool result = _dsHelper.SelectJoinInto("Joint", _dataset.Links,
                    "From ,To ,CaseSensitive caseing,Repository_LinksDestination.Text Correction, Links_RepositorySource.Text Original",
                    string.Format("From ='{0}' and To = '{1}'", _from.Key, _to.Key),
                    "CaseSensitive desc", out dtInnerJoin);
                    DataColumn col = new DataColumn("StrLen", typeof(int), "Len(Original)");
                    dtInnerJoin.Columns.Add(col);
                }
                DataRow[] rows = dtInnerJoin.Select(string.Format("Correction like '%{0}%' and From = '{1}' and to = '{2}'", _txtTranslated.Text, _from.Key, _to.Key));
                if (rows.Length > 0)
                {
                    bool exists = false;
                    foreach (DataRow row in rows)
                    {
                        if (WebUtils.StringParser.InExpression(row["Correction"] as string, _txtTranslated.Text, ((bool)row["caseing"]) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase))
                        {
                            exists = true;
                            break;
                        }
                    }

                    string msg = string.Format("'{0}' is already in a correction entry as '{1}'.\r\nDo you still want to add it to the dictionary?",
                       _txtTranslated.Text, rows[0]["Correction"]);
                    if (exists && MessageBox.Show(this, msg, "Duplicate entry", MessageBoxButtons.YesNo) == DialogResult.No)
                        return;
                }

                //add translation
                int TranslationId = 0;
                int caseSensitiveMatchIndex = -1;
                //not case sensitive
                CustomDict.RepositoryRow[] res = _dataset.Repository.Select(string.Format("Text = '{0}'",
                    _txtTranslated.Text)) as CustomDict.RepositoryRow[];
                if (!_ckbIgnoreCase.Checked)
                    for (caseSensitiveMatchIndex = res.Length - 1; caseSensitiveMatchIndex >= 0; caseSensitiveMatchIndex--)
                    {
                        if (string.Compare(_txtTranslated.Text, res[caseSensitiveMatchIndex].Text) == 0)
                        {
                            break;
                        }
                    }
                else
                    caseSensitiveMatchIndex = 0;

                if (res.Length == 0 || caseSensitiveMatchIndex < 0)
                {
                    reprow = _dataset.Repository.NewRow() as CustomDict.RepositoryRow;
                    reprow.Text = _txtTranslated.Text;
                    _dataset.Repository.AddRepositoryRow(reprow);
                    TranslationId = reprow.Index;
                    _dataset.Repository.AcceptChanges();
                }
                else
                    TranslationId = (caseSensitiveMatchIndex < 0) ? 0 : res[caseSensitiveMatchIndex].Index;
                //add original
                caseSensitiveMatchIndex = -1;
                //not case sensitive
                int CorrectionId = 0;
                res = _dataset.Repository.Select(string.Format("Text = '{0}'", _txtCorrected.Text)) as CustomDict.RepositoryRow[];
                if (!_ckbIgnoreCase.Checked)
                    for (caseSensitiveMatchIndex = res.Length - 1; caseSensitiveMatchIndex >= 0; caseSensitiveMatchIndex--)
                    {
                        if (string.Compare(_txtCorrected.Text, res[caseSensitiveMatchIndex].Text) == 0)
                        {
                            break;
                        }
                    }
                else
                    caseSensitiveMatchIndex = 0;
                if (res.Length == 0 || caseSensitiveMatchIndex < 0)
                {
                    reprow = _dataset.Repository.NewRow() as CustomDict.RepositoryRow;
                    reprow.Text = _txtCorrected.Text;
                    _dataset.Repository.AddRepositoryRow(reprow);
                    _dataset.Repository.AcceptChanges();
                    CorrectionId = reprow.Index;
                }
                else
                    CorrectionId = (caseSensitiveMatchIndex < 0) ? 0 : res[caseSensitiveMatchIndex].Index;
                //Update links table
                CustomDict.LinksRow[] reslink = _dataset.Links.Select(
                    string.Format("SourceIndex = {0} and From = '{1}' and To = '{2}' and DestinationIndex = {3}", TranslationId, _from.Key, _to.Key, CorrectionId)) as CustomDict.LinksRow[];
                CustomDict.LinksRow linkrow = null;
                if (reslink.Length == 0)
                {
                    linkrow = _dataset.Links.NewRow() as CustomDict.LinksRow;
                    linkrow.SourceIndex = TranslationId;
                    linkrow.DestinationIndex = CorrectionId;
                    linkrow.CaseSensitive = !_ckbIgnoreCase.Checked;
                    linkrow.From = _from.Key;
                    linkrow.To = _to.Key;
                    _dataset.Links.AddLinksRow(linkrow);
                    _dataset.Repository.AcceptChanges();
                }
                else
                    linkrow = reslink[0];
                //add the reverse
                CustomDict.LinksRow linkrowReverse = null;
                if (_ckbAddReverse.Checked)
                {
                    reslink = _dataset.Links.Select(
                    string.Format("SourceIndex = {0} and From = '{1}' and To = '{2}' and DestinationIndex = {3}", TranslationId, _to.Key, _from.Key, CorrectionId)) as CustomDict.LinksRow[];

                    if (reslink.Length == 0)
                    {
                        linkrowReverse = _dataset.Links.NewRow() as CustomDict.LinksRow;
                        linkrowReverse.SourceIndex = CorrectionId;
                        linkrowReverse.DestinationIndex = TranslationId;
                        linkrowReverse.CaseSensitive = !_ckbIgnoreCase.Checked;
                        linkrowReverse.From = _to.Key;
                        linkrowReverse.To = _from.Key;
                        _dataset.Links.AddLinksRow(linkrowReverse);
                        _dataset.Repository.AcceptChanges();
                    }
                    else
                        linkrowReverse = reslink[0];
                    //_dataset.Repository.AcceptChanges();
                }
                _btnAddTranslation.Enabled = false;
            }
            catch (Exception ex)
            {

                MessageBox.Show(this, ex.Message, "Dataset error");

            }
        }

        private void tabControl1_Selected(object sender, TabControlEventArgs e)
        {
            if (e.TabPageIndex == 0)
                return;

            if (_dsHelper == null)
            {
                DataSet ds = _dataset.Tables[0].DataSet;
                //ds.Relations.Add(
                _dsHelper = new DataSetHelper(ds);
            }
            DataTable dtInnerJoin;
            bool result = _dsHelper.SelectJoinInto("Joint", _dataset.Links,
                "SourceIndex, DestinationIndex, From , To , Links_RepositorySource.Text Original,Repository_LinksDestination.Text Correction, CaseSensitive caseing",
                "", "CaseSensitive desc", out dtInnerJoin);
            DataColumn col = new DataColumn("StrLen", typeof(int));
            col.Expression = "Len(Original)";
            dtInnerJoin.Columns.Add(col);

            switch (e.TabPageIndex)
            {
                case 1:

                    this._dataGridViewTranslation.DataSource = new DataView(dtInnerJoin,
                        string.Format("From ='{0}' and To = '{1}'", _from.Key, _to.Key),
                        "StrLen, caseing desc, Original", DataViewRowState.CurrentRows);
                    this._dataGridViewTranslation.Columns["SourceIndex"].Visible = false;
                    this._dataGridViewTranslation.Columns["DestinationIndex"].Visible = false;
                    break;
                case 2:
                    this._dataGridViewReverseTranslation.DataSource = new DataView(dtInnerJoin,
                        string.Format("From ='{0}' and To = '{1}'", _to.Key, _from.Key),
                        "StrLen desc, caseing desc, Correction", DataViewRowState.CurrentRows);
                    this._dataGridViewReverseTranslation.Columns["SourceIndex"].Visible = false;
                    this._dataGridViewReverseTranslation.Columns["DestinationIndex"].Visible = false;
                    break;
            }

        }

        private void _txtDesired_TextChanged(object sender, EventArgs e)
        {
            _btnAddTranslation.Enabled = this._txtCorrected.Text.Length > 0 && _txtTranslated.Text.Length > 0;
        }

        private void CustomDictionaryForm_Activated(object sender, EventArgs e)
        {
            string languageCode = _parent._cbxTo.ComboBox.SelectedValue.ToString();
            _parent.ChangeInputLanguage(languageCode, false);
        }



        private void UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            DataRowView drv = e.Row.DataBoundItem as DataRowView ;
            DataRow row = drv.Row;
            int sourceIndex = (int)drv.Row["SourceIndex"];
            int destinationIndex = (int)drv.Row["DestinationIndex"];
            DataRow[] rows = _dataset.Links.Select(string.Format("From ='{0}' and To = '{1}' and SourceIndex = {2} and DestinationIndex = {3}", _from.Key, _to.Key, sourceIndex, destinationIndex));
            if (rows != null && rows.Length > 0)
            {
                foreach (DataRow d in rows) d.Delete();
                _dataset.Links.AcceptChanges();
            }
            rows = _dataset.Links.Select(string.Format("From ='{0}' and To = '{1}' and SourceIndex = {2} and DestinationIndex = {3}", _to.Key, _from.Key, sourceIndex, destinationIndex));
            if (rows != null && rows.Length > 0)
            {
                foreach (DataRow d in rows) d.Delete();
                _dataset.Links.AcceptChanges();
            }

            rows = _dataset.Repository.Select(string.Format("Index = {0} or Index = {1}",sourceIndex, destinationIndex));
            if (rows != null && rows.Length > 0)
            {
                foreach(DataRow d in rows) d.Delete();
                _dataset.Repository.AcceptChanges();
            }

        }

        private void _btnDelete_Click(object sender, EventArgs e)
        {
            DataGridViewRow r = _dataGridViewTranslation.CurrentRow;
            if (r != null)
            {
                UserDeletingRow(_dataGridViewTranslation, new DataGridViewRowCancelEventArgs(r));
                tabControl1_Selected(this, new TabControlEventArgs(_translationTabPage, 1, TabControlAction.Selected));
            }

        }

        private void _btnDelete2_Click(object sender, EventArgs e)
        {
            DataGridViewRow r = _dataGridViewReverseTranslation.CurrentRow;
            if (r != null)
            {
                UserDeletingRow(_dataGridViewReverseTranslation, new DataGridViewRowCancelEventArgs(r));
                tabControl1_Selected(this, new TabControlEventArgs(_translationTabPage, 2, TabControlAction.Selected));
            }
        }

    }
}